"""
 Page request handler
 
 @author Jean-Lou Dupont

GET   /page/NS:X/
POST  /page/NS:X/
 
 NS => rawName | Name
 X  => title name
 
"""
__all__ = ['main']
 
import os, sys, string, time
import logging
import random
import urllib

import wsgiref.handlers
from google.appengine.ext import webapp
from google.appengine.api import users

from libs.wiki import template
from libs.wiki.page import *
from libs.wiki.title import *
from libs.wiki.namespace import *

from libs.user.prefs import UserPrefs

class ControllerPage( webapp.RequestHandler ):
    """
        Handles 'wiki-ized' requests
    """

    def get( self, titleNameCoded ):
        
        titleName = urllib.unquote(titleNameCoded)
        
        #Verify title validity
        title = self._verifyTitle(titleName)
        if (title is None):
            return
        
        #Verify title's namespace validity
        ns = self._verifyNamespace(title)
        if (ns is None):
            return
        
        #Is it a page from a 'raw' namespace?
        # ns is a Namespace instance
        if (ns.isRaw()):
            return self._handleRawGet(title)

        # Page already exists OR needs to be generated?
        titleRaw = self._generateRawTitle(title)
        
        self.response.headers['Cache-Control'] = 'no-cache, must-revalidate, max-age=0'
        self.response.headers['x-wb-title'] = titleName
        #self.response.headers['ETag'] =  
        #self.response.headers['Last-Modified'] = LocalTimeInRFC1134Date()
        
        user = users.get_current_user()
        group_admin = ''
        user_name = ''
        user_uid   = ''  
        if user:
            user_name  = user.nickname()
            user_prefs = UserPrefs.create( user )
            user_uid = user_prefs.uid
            if (users.is_current_user_admin()):
                group_admin = 'admin'
                
        user_is_admin = group_admin.find( 'admin' ) != -1
                
        template_values = { 'title':        titleName,
                            'username':     user_name,
                            'useruid':      user_uid, 
                            'usergroups':   group_admin, 
                            'is_admin':     user_is_admin                            
                           }
        
        #logging.info("Page.GET page [%s] generated from template[%s]" % (titleName, str(titleRaw)) )        

        try:
            #db_template_loader.Loaded.reset();
            
            content   = template.render( str(titleRaw), template_values)
            
            #liste = db_template_loader.Loaded.list
            #templates = "<!--<templates>%s</templates>-->" % JsonWriter().write( liste )
            self.response.out.write( content ) #+ templates )
            #logging.info('ControllerPage.get: templates used: %s' % db_template_loader.Loaded.list)
            
        except Exception, e:
            logging.error('ControllerPage.get: exception, msg=%s' % e.message )
            self._handleNotFound(titleName,template_values, e)
    
    def _handleNotFound(self, titleName, template_values, e):
        """
        Handles 'page not found' condition
        """
        try:
            notfoundtitle = Title('raw:NotFound')
            template_values['error'] = e.message
            self.response.out.write( template.render( str(notfoundtitle), template_values))
            self.response.headers['Cache-Control'] = 'max-age=3600'  
        except:
            logging.error("ControllerPage._handleNotFound: exception raised")
            self.response.set_status( 404 )
          
    def _handleRawGet(self,title):
        """
            Provides an 'edit' page for a title
        """
        page = Page.getFromStore( title, False )
        if (page.valid() ):
            try:
                etag = self.request.headers['If-None-Match']
            except:
                etag = None
                
            if (etag):
                if ( etag == page.etag ):
                    self.response.set_status( 304 )
                    return

        #IE6: whenever IE sees a 'Last-Modified' header, it assumes it can use 'conditional GET'...
        #self.response.headers['Last-Modified'] = toRFC1123Date( str( page.modified ) )
        if ( page.valid() ):
            logging.info("Page.GET (raw) page [%s] is valid" % str(title) )            
            content = page.content
        else:
            logging.info("Page.GET (raw) page [%s] INVALID" % str(title) )   
            content = ''


        #Get the page's 'base' namespace
        baseTitle = self._generateBaseTitle(title)
        titre = str( baseTitle )
        
        #template_values = { 'content':   content,
        #                    'link':      '#%s' % titre,
        #                    'title':     titre,
        #                    'title_body':titre
        #                   }
        
        etag = '"%s"' % str( page.etag )
        
        try:
            self.response.headers['x-wb-title'] = str( title )
            self.response.headers['x-wb-editable'] = 'true'
            #self.response.headers['Expires'] = '-1'
            self.response.headers['Cache-Control'] = 'private, s-maxage=0, max-age=0, must-revalidate'  
            self.response.headers['ETag'] = etag
        except Exception,e:
            logging.error('PAGE.get (raw): EXCEPTION msg='+e.message)
            
        #self.response.out.write(template.render('editpage.html', template_values))
        self.response.out.write( content )

    def post(self, titleNameCoded ):
        """
            Creates/updates a page in the datastore
        """
        titleName = urllib.unquote(titleNameCoded)
        
        logging.info("POST page [%s]" % titleName)

        #Verify title
        title = self._verifyTitle(titleName)
        if (title is None): 
            return
        
        #Verify title's namespace validity
        ns = self._verifyNamespace(title)
        if (ns is None):
            return

        #Verify we are in a 'raw' namespace
        if (not ns.isRaw()):
            self.response.headers['x-wb-exception'] = 'wrong_namespace'
            self.response.set_status( 400 ) #Bad Request
            self.response.out.write( 'wrong namespace' )
            #logging.info( 'ControllerPage.post: wrong namespace' )
            return

        #Is the user allowed this operation?
        if (not users.is_current_user_admin()):
            self.response.headers['x-wb-exception'] = 'permission_insufficient'
            self.response.set_status( 403 ) #Forbidden
            self.response.out.write( 'permission unsufficient' )
            return

        #===================
        #Everything is fine!
        #===================
        
        page = Page.getFromStore( title, False )
        page.content = self.request.body
        
        try:
            key = page.save( timeout=600 ) #cache for 10minutes: 10*60
            self.response.set_status( 200 )
            #logging.info("POST page: title[%s] save key[%s]" % (titleName,key))            
        except Exception,e:
            self.response.headers['x-wb-exception'] = 'save_failed'            
            self.response.set_status( 500 )
            logging.info("POST page: EXCEPTION raised, msg=%s" % e)
            self.response.out.write( 'save failed, msg=%s' % e)
        
        
    def _verifyTitle(self, titleName):
        """Returns a 'Title' instance
        """
        try:
            title = Title(titleName)
        except TitleException,e:
            logging.info("_verifyTitle, exception: %s" % e)
            self.response.headers['x-wb-exception'] = 'title'
            self.response.set_status( 500 ) #Server Error
            title = None
        return title
        
    def _verifyNamespace(self, title):
        """ Returns 'Namespace' instance
        """
        #Verify title's namespace validity
        try:
            #nsname is a string
            nsname = title.namespace
            ns = Namespaces.fromName(nsname)            
        except:
            logging.info("_verifyNamespace exception nsname[%s]" % nsname)
            self.response.headers['x-wb-exception'] = 'namespace'
            self.response.set_status( 500 ) #Server Error
            ns = None
        
        return ns        
    
    def _generateRawTitle(self, title):
        try:
            titlename = title.key
            nsname = title.namespace
            nsRaw  = Namespaces.createRaw(nsname)
            nsRawName = str(nsRaw)
            titleRaw = Title.fromParts(nsRawName, titlename)
        except NamespaceException, e:
            logging.info("_generateRawTitle, exception: %s" % e)
            return None
        except:
            return None
        return titleRaw
    
    def _generateBaseTitle(self, title):
        """
            Given a page in a 'raw' namespace,
            creates a corresponding page in the 'base' namespace
        """
        try:
            titlename = title.key
            nsname = title.namespace
            nsBase  = Namespaces.createBase(nsname)
            nsBaseName = str(nsBase)
            titleBase = Title.fromParts(nsBaseName, titlename)
        except NamespaceException, e:
            logging.info("_generateBaseTitle, exception: %s" % e)
            return None
        except:
            return None
        return titleBase
    
    
    def _loadRaw(self, title):
        try:
            titleName = title.key
            nsname =    title.namespace
            nsRaw  =    Namespaces.createRaw(nsname)
            titleRaw =  Title(nsRaw,titleName)
        except:
            return None
        return Page.load(titleRaw)
    

#========================================================================================================

def toRFC1123Date(timestamp):
    rdate = timestamp.split('.')[0]
    sdate = time.strptime( rdate, "%Y-%m-%d %H:%M:%S" )
    return time.strftime( "%a, %d %b %Y %H:%M:%S +0000", sdate )

def LocalTimeInRFC1134Date():
    #(2008, 8, 13, 0, 32, 55, 2, 226, 0)
    #date = time.strptime(time.localtime(), "%Y")
    return time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.localtime())


#========================================================================================================

__URLMAP = [('/page/(.*)/', ControllerPage)]

def main():
  application = webapp.WSGIApplication(__URLMAP, debug=True)
  wsgiref.handlers.CGIHandler().run(application)

#========================================================================================================
if __name__ == "__main__":
    main()